﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Abp.Application.Services.Dto;
using Abp.Runtime.Caching;
using DevM.Development.Projects.Dto;
using DevM.Development.Resources;
using DevM.Sessions;
using Microsoft.AspNetCore.Http;
using System.Linq;
using Abp.Linq.Extensions;
using DevM.Authorization.Users;
using DevM.Authorization.Roles;
using DevM.Roles.Dto;
using DevM.Development.Resources.Dto;

namespace DevM.Development.Projects
{
    public class ProjectAppService : DevMAppServiceBase, IProjectAppService
    {
        private readonly ISessionAppService sessionAppService;
        private readonly IHttpContextAccessor httpContextAccessor;
        private readonly ResourceManager resourceManager;
        private readonly ICacheManager cacheManager;
        private readonly ProjectManager projectManager;
        private readonly ProjectStore projectStore;
        private readonly UserManager userManager;
        private readonly RoleManager roleManager;

        public ProjectAppService(ISessionAppService sessionAppService, IHttpContextAccessor httpContextAccessor, ResourceManager resourceManager, ICacheManager cacheManager, ProjectManager projectManager, ProjectStore projectStore, UserManager userManager, RoleManager  roleManager)
        {
            this.sessionAppService = sessionAppService;
            this.httpContextAccessor = httpContextAccessor;
            this.resourceManager = resourceManager;
            this.cacheManager = cacheManager;
            this.projectManager = projectManager;
            this.projectStore = projectStore;
            this.userManager = userManager;
            this.roleManager = roleManager;
        }

        public async Task<EnvironmentDto> CreateEnvironment(AddEnvironmentInput input)
        {
            var environment = ObjectMapper.Map<Environment>(input);
            var currentUserInfomation = await sessionAppService.GetCurrentLoginInformations();
            environment.CreationTime = DateTime.Now;
            environment.CreatorUserId = currentUserInfomation.User?.Id ?? 0;
            environment.TenantId = currentUserInfomation.Tenant?.Id;
            return ObjectMapper.Map<EnvironmentDto>(await projectManager.AddEnvironment(environment));
        }

        public async Task<ProjectDto> CreateProject(AddProjectInput input)
        {
            var project = ObjectMapper.Map<Project>(input);
            var currentUserInfomation = await sessionAppService.GetCurrentLoginInformations();
            project.CreationTime = DateTime.Now;
            project.CreatorUserId = currentUserInfomation.User?.Id ?? 0;
            project.TenantId = currentUserInfomation.Tenant?.Id;
            return ObjectMapper.Map<ProjectDto>(await projectManager.AddProject(project));
        }


        public async Task DeleteEnvironment(EntityDto<long> environmentId)
        {
            var currentUserInfomation = await sessionAppService.GetCurrentLoginInformations();
            await projectManager.DeleteEnvironment(currentUserInfomation.User?.Id ?? 0, environmentId.Id);
        }

        public async Task DeleteProject(EntityDto<long> projectId)
        {
            var currentUserInfomation = await sessionAppService.GetCurrentLoginInformations();
            await projectManager.DeleteProject(currentUserInfomation.User?.Id ?? 0, projectId.Id);
        }


        public async Task<List<RoleDto>> GetAllRoles()
        {
            return ObjectMapper.Map<List<RoleDto>>(roleManager.Roles.ToList());
        }

        public async Task<EnvironmentDto> GetEnvironment(EntityDto<long> environmentId)
        {
            return ObjectMapper.Map< EnvironmentDto > (await projectManager.GetEnvironmentById(environmentId.Id));
        }

        public async Task<List<EnvironmentDto>> GetEnvironmentList(EntityDto<long> projectId)
        {
            return ObjectMapper.Map<List<EnvironmentDto>>( await projectManager.GetEnvironmentsByProjectId(projectId.Id));
        }

        public async Task<ProjectDto> GetProject(EntityDto<long> projectId)
        {
            return ObjectMapper.Map<ProjectDto>(await projectManager.GetProjectById(projectId.Id));
        }

        public async Task<PageOutput<ProjectDto>> GetProjectList(GetProjectListInput input)
        {
            var currentUserInfomation = await sessionAppService.GetCurrentLoginInformations();
            var user = await userManager.GetUserByIdAsync(currentUserInfomation.User.Id);

            var roleIds =userManager.GetRolesAsync(user).Result.Select(rn=> roleManager.GetRoleByNameAsync(rn).Result).Select(r=>r.Id).ToList();




            //只查在指定用户组的项目
            var dataset = projectManager.Projects.Where(p => roleIds.Contains(p.MemberRoleId) || p.CreatorUserId == user.Id).OrderByDescending(p=>p.Id);
            var items = dataset.Skip(input.SkipCount).Take(input.MaxResultCount).ToList();
            var total = dataset.Count();
            var result = new PageOutput<ProjectDto>
            {
                Items = ObjectMapper.Map<List<ProjectDto>>(items),
                TotalCount = total
            };
            var role = await roleManager.GetRoleByIdAsync(1);
            foreach (var item in result.Items)
            {
                if(item.MemberRoleId>0)
                    item.RoleName = (await roleManager.GetRoleByIdAsync(item.MemberRoleId))?.Name ?? "";
                item.TotalEnvironment = projectManager.Environments.Where(e => e.ProjectId == item.Id).Count();

            }
            return result;
        }

        public async Task<EnvironmentDto> UpdateEnvironment(UpdateEnvironmentInput input)
        {
            var environment = ObjectMapper.Map<Environment>(input);
            var currentUserInfomation = await sessionAppService.GetCurrentLoginInformations();
            environment.LastModificationTime = DateTime.Now;
            environment.LastModifierUserId = currentUserInfomation.User?.Id ?? 0;
            environment.TenantId = currentUserInfomation.Tenant?.Id;
            return ObjectMapper.Map<EnvironmentDto>(await projectManager.UpdateEnvironment(environment));
        }

        public async Task<ProjectDto> UpdateProject(UpdateProjectInput input)
        {
            var project = ObjectMapper.Map<Project>(input);
            var currentUserInfomation = await sessionAppService.GetCurrentLoginInformations();
            project.LastModificationTime = DateTime.Now;
            project.LastModifierUserId = currentUserInfomation.User?.Id ?? 0;
            project.TenantId = currentUserInfomation.Tenant?.Id;
            return ObjectMapper.Map<ProjectDto>(await projectManager.UpdateProject(project));
        }
    }
}
